import json
import os.path
import sys
import re
import requests
from bs4 import BeautifulSoup


def download_bing_images(num_image=20):
    """
    下载jayjay前i张壁纸
    :param num_image: 前几张
    :return: 返回下载的壁纸
    """

    # 1.发送请求
    url = "https://cn.bing.com/images/search?q=jayjay%e7%94%b5%e8%84%91%e5%a3%81%e7%ba%b8%e9%ab%98%e6%b8%85%e5%85%a8%e5%b1%8f4k&form=IACFSM&first=1"
    response = requests.get(url)

    # 2.检查请求是否成功
    if response.status_code != 200:
        print(f"网页请求失败，状态码为：{response.status_code}")
        return False

    # 3.解析html内容（给食材和做菜工具给大厨，以页的形式阅读）
    page = BeautifulSoup(response.text, "html.parser")

    # 4.查找所有图片元素
    image_elements = page.find_all('a', class_="iusc")
    if not image_elements:
        print("未找到图片元素")
        return False

    # 5.创建下载目录
    download_dir = r"D:\Python\宠物壁纸4k"
    if not os.path.exists(download_dir):
        os.makedirs(download_dir)
        print(f"创建下载目录为:{download_dir}")

    # 6.设置请求头，模拟浏览器访问
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
        'Referer': 'https://cn.bing.com/',  # 设置为图片所在网站的首页或搜索页
        'Sec-Fetch-Dest': 'document',
        'Sec-Fetch-Mode': 'navigate',
        'Sec-Fetch-Site': 'same-origin',
    }

    # 7.记录下载结果
    success_count = 0
    failed_count = 0
    failed_list = []

    # 8.下载前几张
    for i, element in enumerate(image_elements[:num_image]):
        try:
            # (1)获取m属性的JSON数据
            m_data = element.get("m")
            if not m_data:
                print(f"第{i+1}张图片没有m属性，跳过")
                failed_count += 1
                failed_list.append(f"图片{i+1}：无m属性")
                continue

            # (2)解析JSON数据
            image_info = json.loads(m_data)
            image_url = image_info.get("murl")
            image_title = image_info.get('t', f"image_{i}")

            if not image_url:
                print(f"第{i+1}张图片是无效的url地址，跳过")
                failed_count += 1
                failed_list.append(f"图片{i+1}：无有效url")
                continue

            # (3)清理文件名字
            clean_titel = re.sub(r'[<>:"/\\|?*]', '', image_title)
            file_extension =os.path.splitext(image_url)[1]
            if not file_extension or len(file_extension) > 5:
                file_extension = ".jpg"

            # (4)构建文件名和完整的文件路径
            filename = f"{clean_titel}_{i}{file_extension}"
            filepath = os.path.join(download_dir, filename)

            # (5)下载文件
            print(f"正在下载({i+1}/{num_image}):{image_title}")  # 这是对于单张照片而言的，在遍历
            img_response = requests.get(image_url, headers=headers, stream=True, timeout=30)

            if img_response.status_code == 200:
                # 8.(5).1下载图片——>将图片写入文件夹中
                with open(filepath, 'wb') as f:
                    for chunk in img_response.iter_content(chunk_size=8192):
                        if chunk:
                            f.write(chunk)

                # 8.(5).2验证文件是否真正保存成功
                if os.path.exists(filepath) and os.path.getsize(filepath) > 0:
                    print(f"保存成功:{filename}")
                    success_count += 1
                else:
                    print(f"保存失败：{filename}")
                    failed_count += 1
                    failed_list.append(f"图片{i+1}：保存失败")

            else:
                print(f"下载失败，HTTP状态码：{img_response.status_code}")
                failed_count += 1
                failed_list.append(f"图片{i+1}：HTTP错误{img_response.status_code}")

        except Exception as e:
            print(f"处理图片{i+1}出错：{str(e)}")
            failed_count += 1
            failed_list.append(f"图片{i+1}：异常{str(e)}")


    # 9.结束遍历循环，报告总结果——>成功数，失败数（失败详情）
    print("\n" + "=" * 50)
    print("下载完成总结：")
    print(f"下载成功：{success_count}张")
    print(f"下载失败：{failed_count}张")

    if failed_list:
        print("\n失败详情：")
        for failure in failed_list:
            print(f" - {failure}")

    # 10.检查目标文件夹中的图片文件（总体质量检查）
    downloaded_files = [f for f in os.listdir(download_dir) if
        f.lower().endswith(('.jpg', 'jpeg', 'png', 'git', 'bmp'))]

    print(f"\n目标文件夹中实际存在图片文件：{len(downloaded_files)}张")

    if downloaded_files:
        print("文件列表：")
        for file in downloaded_files:
            file_size = os.path.getsize(os.path.join(download_dir, file))  # 这里又拼接了一次，因为在这个循环里，file才是每个文件在该目录下的文件名
            print(f" - {file} ({file_size}字节)")

    # 11.如果有失败的情况，返回并报错
    if failed_count > 0:
        print(f"下载有问题，有{failed_count}张失败")
        return False
    else:
        print("全部下载成功")
        return True

# 运行程序
if __name__ =="__main__":

    # 获取函数括号中的内容（要下载的张数）
    if len(sys.argv) > 1:  # 如果存在
        try:
            # 尝试将获取到的字符串转为整数
            num_images = int(sys.argv[1])
            print(f"将从命令行参数下载{num_images}张图片")

        except ValueError:
            # 如果字符串是“abc”，无法转为整数，抛出错误
            print("无效的参数，使用默认值4张")
            num_images = 4

    # 如果括号内不存在内容
    else:
        num_images = 4 # 默认值

    # 查看函数的返回值，全部下载成功没有一个错误才为True
    success = download_bing_images(num_images)
    # 如果有失败，可以在这里进行额外处理或报错
    if not success:
        exit(1)  # 非零退出码表示程序执行有错误






